package com.ruoyi.xag.service.impl;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.utils.http.HttpUtils;

import com.ruoyi.permission.Dao.SerDevicePermi;
import com.ruoyi.permission.mapper.SerDevicePermiMapper;
import com.ruoyi.xag.domain.IotDeviceInfo;
import com.ruoyi.xag.domain.datapoints.SoilSenorDataPoints;
import com.ruoyi.xag.domain.datapoints.Weather;
import com.ruoyi.xag.domain.datapoints.WeatherSenorDataPoints;
import com.ruoyi.xag.domain.iotdevice.IotDevice;
import com.ruoyi.xag.mapper.DeviceMapper;
import com.ruoyi.xag.service.DeviceService;
import com.ruoyi.xag.service.SessionService;
import com.ruoyi.xag.utils.CreateSignature;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LiSuxuan
 * @date 2021年 06月 23日 19:26
 */
@Service
    public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private SessionService sessionService;


    @Autowired
    private SerDevicePermiMapper permiMapper;

    /**
     * IOT 客户唯一ID
     */
    @Value("${iot.clientId}")
    private String clientId;

    /**
     * IOT 设备密钥
     */
    @Value("${iot.secret}")
    private String secret;

    /**
     * IOT 设备密钥
     */
    @Value("${iot.iotUrl}")
    private String iotUrl;

    /**
     * IOT 用户ID
     */
    @Value("${iot.account}")
    private String account;

    /**
     * IOT 用户密码
     */
    @Value("${iot.password}")
    private String password;


    /**
     * 查询用户设备列表
     * offset=0 开始数
     * num=100 结束数
     *
     * @return 列表数据
     */
    @Override
    public List<IotDevice> selectDeviceList() throws IOException, ParseException {
        String session = sessionService.checkSession();
        String authenticationUrl = CreateSignature.mergeAuthenticationUrl(clientId, secret);
        String url = iotUrl + "/v5/clients/" + account + "/devices";
        // 发送 HTTP 请求，返回 JSON 信息
        String deviceListJson = HttpUtils.sendGetAddHeader(url, authenticationUrl + "&offset=0&num=100", "UTF-8", session);
        Object devices = JSON.parseObject(deviceListJson).get("devices");
        List<IotDevice> iotDevices = JSON.parseArray(devices.toString(), IotDevice.class);
        for(IotDevice iotDevice:iotDevices){
            IotDeviceInfo iotDeviceInfo = deviceMapper.selectIotDeviceByDeviceId(iotDevice.getId());
//            IotDeviceInfo iotDeviceInfo = new IotDeviceInfo();
            String onlineState = String.valueOf(iotDevice.getStatus()).equals("1")?"在线":"离线";
            iotDeviceInfo.setDeviceStatus(onlineState);
//            iotDeviceInfo.setDeviceId(iotDevice.getId());
            iotDeviceInfo.setBattery(Double.valueOf(iotDevice.getBattery()));
            Double longitude_ori = Double.valueOf(iotDevice.getLocation().getLongitude());
            Double latitude_ori = Double.valueOf(iotDevice.getLocation().getLatitude());
            BigDecimal longBigDecimal = new BigDecimal(longitude_ori);
            BigDecimal laBigDecimal = new BigDecimal(latitude_ori);
            Double longitude = longBigDecimal.setScale(5,BigDecimal.ROUND_DOWN).doubleValue();
            Double latitude = laBigDecimal.setScale(5,BigDecimal.ROUND_DOWN).doubleValue();
            iotDeviceInfo.setLongitude(longitude);
            iotDeviceInfo.setLatitude(latitude);
            deviceMapper.updateDevice(iotDeviceInfo);
            //需要更新的信息
//            Double longitude = iotDevice.getLocation().getLongitude();
//            Double latitude = iotDevice.getLocation().getLatitude();
            Double battery = iotDevice.getBattery();
            Date date = new Date();
            // 创建SimpleDateFormat对象，指定字符串的日期格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 调用format() 方法，格式化时间，转换为指定格式字符串
            String now = sdf.format(date);
            Date updateTime = sdf.parse(now);
            //更新权限设备表中气象土壤设备的信息
            SerDevicePermi devicePermiInfo = permiMapper.selectByDeviceSerial(iotDeviceInfo.getDeviceId());
            devicePermiInfo.setOnlineState(onlineState);
            devicePermiInfo.setLongitude(longitude);
            devicePermiInfo.setLatitude(latitude);
            devicePermiInfo.setBattery(battery);
            permiMapper.updateByPrimaryKeySelective(devicePermiInfo);
        }
        return iotDevices;
    }

    /**
     * 根据设备ID拉取气象传感器最近一条数据
     *
     * @param deviceId 根据设备ID新增
     * @return 影响行数
     */
    @Override
    public int insertWeatherDataPointLast(String deviceId) throws IOException {
        String session = sessionService.checkSession();
        String authenticationUrl = CreateSignature.mergeAuthenticationUrl(clientId, secret);
        String url = iotUrl + "/v5/clients/" + account + "/devices/" + deviceId + "/datapoints/last";
        // 发送 HTTP 请求，返回 JSON 信息
        String weatherDataLast = HttpUtils.sendGetAddHeader(url, authenticationUrl + "&encoding=json&data_type=1", "UTF-8", session);
        WeatherSenorDataPoints weatherSenorDataPoints = JSON.parseObject(weatherDataLast, WeatherSenorDataPoints.class);
        System.out.println(weatherSenorDataPoints);
        weatherSenorDataPoints.setDeviceId(deviceId);
        // 修改降雨量为当前数据 获得数据是历史降雨量累加值，替换为当前一小时降雨量的值
//        WeatherSenorDataPoints weatherDataLastRainfall = deviceMapper.selectWeatherDataLast("W863320045453949");
        WeatherSenorDataPoints weatherDataLastRainfall = deviceMapper.selectWeatherDataLast(deviceId);
        Weather data = weatherSenorDataPoints.getData();
        data.setRainfallAll(data.getRainfall())
                .setRainfall(data.getRainfall() - weatherDataLastRainfall.getData().getRainfallAll());
        weatherSenorDataPoints.setData(data);
        System.out.println(weatherSenorDataPoints);
        int i = deviceMapper.insertWeatherDataPoints(weatherSenorDataPoints);
        System.out.println(i);
        return i;
    }


    /**
     * 根据设备ID拉取土壤传感器最近一条数据
     *
     * @param deviceId 根据设备ID新增
     * @return 影响行数
     */
    @Override
    public int insertSoilDataPointLast(String deviceId) throws IOException {
        String session = sessionService.checkSession();
        String authenticationUrl = CreateSignature.mergeAuthenticationUrl(clientId, secret);
        String url = iotUrl + "/v5/clients/" + account + "/devices/" + deviceId + "/datapoints/last";
        // 发送 HTTP 请求，返回 JSON 信息
        String weatherDataLast = HttpUtils.sendGetAddHeader(url, authenticationUrl + "&encoding=json&data_type=1", "UTF-8", session);
        SoilSenorDataPoints soilSenorDataPoints = JSON.parseObject(weatherDataLast, SoilSenorDataPoints.class);
        soilSenorDataPoints.setDeviceId(deviceId);
        int i = deviceMapper.insertSoilDataPoints(soilSenorDataPoints);
        System.out.println(soilSenorDataPoints);
        return i;
    }

    /**
     * 根据起止时间查询土壤传感器数据
     *
     * @param deviceId 设备ID 唯一索引
     * @param start    开始时间
     * @param end      截止时间
     * @return 集合
     */
    @Override
    public List<SoilSenorDataPoints> selectSoilHistoryData(String deviceId, int start, int end) {
        return deviceMapper.selectSoilHistoryData(deviceId, start, end);
    }

    /**
     * 根据起止时间查询气象传感器数据
     *
     * @param deviceId 设备ID 唯一索引
     * @param start    开始时间
     * @param end      截止时间
     * @return 集合
     */
    @Override
    public List<WeatherSenorDataPoints> selectWeatherHistoryData(String deviceId, int start, int end) {
        return deviceMapper.selectWeatherHistoryData(deviceId, start, end);
    }
    /**
     * 根据起止时间查询土壤传感器数据
     *
     * @param deviceId 设备ID 唯一索引
     * @param start    开始时间
     * @param end      截止时间
     * @return 集合
     */
    @Override
    public List<SoilSenorDataPoints> selectSoilHistoryData2(String deviceId, String start, String end) {
        return deviceMapper.selectSoilHistoryData2(deviceId, start, end);
    }

    /**
     * 根据起止时间查询气象传感器数据
     *
     * @param deviceId 设备ID 唯一索引
     * @param start    开始时间
     * @param end      截止时间
     * @return 集合
     */
    @Override
    public List<WeatherSenorDataPoints> selectWeatherHistoryData2(String deviceId, String start, String end) {
        return deviceMapper.selectWeatherHistoryData2(deviceId, start, end);
    }

    /**
     * 查询气象传感器最近一条数据，用于首页展示
     *
     * @param deviceId 设备唯一ID
     * @return 封装数据对象
     */
    @Override
    public WeatherSenorDataPoints selectWeatherDataLast(String deviceId) {
        return deviceMapper.selectWeatherDataLast(deviceId);
    }

    /**
     * 查询土壤传感器最近一条数据，用于首页展示
     *
     * @param deviceId 设备唯一ID
     * @return 封装数据对象
     */
    @Override
    public SoilSenorDataPoints selectSoilDataLast(String deviceId) {
        return deviceMapper.selectSoilDataLast(deviceId);
    }

    /**
     * 根据设备ID查询设备状态
     *
     * @param deviceId 设备ID
     * @return 设备状态
     */
    @Override
    public IotDevice selectDeviceInfo(String deviceId) throws IOException {
        String session = sessionService.checkSession();
        String authenticationUrl = CreateSignature.mergeAuthenticationUrl(clientId, secret);
        String url = iotUrl + "/v5/clients/" + account + "/devices/" + deviceId;
        // 发送 HTTP 请求，返回 JSON 信息
        String deviceInfo = HttpUtils.sendGetAddHeader(url, authenticationUrl, "UTF-8", session);
        return JSON.parseObject(deviceInfo, IotDevice.class);
    }
    // 返回当前所有设备（不是通过官方接口，通过官方接口改不了别名）
    public List<IotDeviceInfo> selectAllIotDevice(){
        return deviceMapper.selectAllIotDevice();
    }
    //根据条件获取设备
    public List<IotDeviceInfo> selectIotDeviceByCondition(List<SerDevicePermi> serDevicePermiList){
        List<IotDeviceInfo> iotDeviceInfos = deviceMapper.selectAllIotDevice();
        if(!serDevicePermiList.isEmpty()) {
            iotDeviceInfos = iotDeviceInfos.stream()
                    .filter(filteredDevcieInfo -> serDevicePermiList.stream()
                            .anyMatch(serDevicePermi -> serDevicePermi.getDeviceSerial().equals(filteredDevcieInfo.getDeviceId())))
                    .collect(Collectors.toList());
        }
        return iotDeviceInfos;
    }
    // 修改设备名称
    public int updateDeviceNickName(IotDeviceInfo iotDeviceInfo){
        return deviceMapper.updateDeviceNickName(iotDeviceInfo);
    }
    public int updateDeviceInfo(IotDeviceInfo iotDeviceInfo){
        return deviceMapper.updateDevice(iotDeviceInfo);
    }
}
